// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/renderer/skia_benchmarking_extension.h"

#include <stddef.h>

#include "base/values.h"
#include "skia/ext/benchmarking_canvas.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkGraphics.h"

namespace {

testing::AssertionResult HasArg(const base::ListValue* args,
    const char name[])
{
    const base::DictionaryValue* arg;

    for (size_t i = 0; i < args->GetSize(); ++i) {
        if (!args->GetDictionary(i, &arg) || arg->size() != 1)
            return testing::AssertionFailure() << " malformed argument for index "
                                               << i;

        if (arg->HasKey(name))
            return testing::AssertionSuccess() << " argument '" << name
                                               << "' found at index " << i;
    }

    return testing::AssertionFailure() << "argument not found: '" << name << "'";
}

}

namespace content {

TEST(SkiaBenchmarkingExtensionTest, BenchmarkingCanvas)
{
    SkGraphics::Init();

    // Prepare canvas and resources.
    SkCanvas canvas(100, 100);
    skia::BenchmarkingCanvas benchmarking_canvas(&canvas);

    SkPaint red_paint;
    red_paint.setColor(SkColorSetARGB(255, 255, 0, 0));
    SkRect fullRect = SkRect::MakeWH(SkIntToScalar(100), SkIntToScalar(100));
    SkRect fillRect = SkRect::MakeXYWH(SkIntToScalar(25), SkIntToScalar(25),
        SkIntToScalar(50), SkIntToScalar(50));

    SkMatrix trans;
    trans.setTranslate(SkIntToScalar(10), SkIntToScalar(10));

    // Draw a trivial scene.
    benchmarking_canvas.save();
    benchmarking_canvas.clipRect(fullRect);
    benchmarking_canvas.setMatrix(trans);
    benchmarking_canvas.drawRect(fillRect, red_paint);
    benchmarking_canvas.restore();

    // Verify the recorded commands.
    const base::ListValue& ops = benchmarking_canvas.Commands();
    ASSERT_EQ(ops.GetSize(), static_cast<size_t>(5));

    size_t index = 0;
    const base::DictionaryValue* op;
    const base::ListValue* op_args;
    std::string op_name;

    ASSERT_TRUE(ops.GetDictionary(index++, &op));
    EXPECT_TRUE(op->GetString("cmd_string", &op_name));
    EXPECT_EQ(op_name, "Save");
    ASSERT_TRUE(op->GetList("info", &op_args));
    EXPECT_EQ(op_args->GetSize(), static_cast<size_t>(0));

    ASSERT_TRUE(ops.GetDictionary(index++, &op));
    EXPECT_TRUE(op->GetString("cmd_string", &op_name));
    EXPECT_EQ(op_name, "ClipRect");
    ASSERT_TRUE(op->GetList("info", &op_args));
    EXPECT_EQ(op_args->GetSize(), static_cast<size_t>(3));
    EXPECT_TRUE(HasArg(op_args, "rect"));
    EXPECT_TRUE(HasArg(op_args, "op"));
    EXPECT_TRUE(HasArg(op_args, "anti-alias"));

    ASSERT_TRUE(ops.GetDictionary(index++, &op));
    EXPECT_TRUE(op->GetString("cmd_string", &op_name));
    EXPECT_EQ(op_name, "SetMatrix");
    ASSERT_TRUE(op->GetList("info", &op_args));
    EXPECT_EQ(op_args->GetSize(), static_cast<size_t>(1));
    EXPECT_TRUE(HasArg(op_args, "matrix"));

    ASSERT_TRUE(ops.GetDictionary(index++, &op));
    EXPECT_TRUE(op->GetString("cmd_string", &op_name));
    EXPECT_EQ(op_name, "DrawRect");
    ASSERT_TRUE(op->GetList("info", &op_args));
    EXPECT_EQ(op_args->GetSize(), static_cast<size_t>(2));
    EXPECT_TRUE(HasArg(op_args, "rect"));
    EXPECT_TRUE(HasArg(op_args, "paint"));

    ASSERT_TRUE(ops.GetDictionary(index++, &op));
    EXPECT_TRUE(op->GetString("cmd_string", &op_name));
    EXPECT_EQ(op_name, "Restore");
    ASSERT_TRUE(op->GetList("info", &op_args));
    EXPECT_EQ(op_args->GetSize(), static_cast<size_t>(0));
}

} // namespace content
